package com.qdlc.p2p.biz.core.tender.impl;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.qdlc.p2p.biz.core.tender.AbstractStrategy;
import com.qdlc.p2p.biz.service.AccountLogService;
import com.qdlc.p2p.biz.service.InterestService;
import com.qdlc.p2p.common.constant.BorrowCollectionStatus;
import com.qdlc.p2p.common.constant.BorrowTenderStatus;
import com.qdlc.p2p.common.constant.BorrowTenderType;
import com.qdlc.p2p.common.constant.BorrowType;
import com.qdlc.p2p.common.constant.ExperienceStatus;
import com.qdlc.p2p.common.constant.ExperienceTenderStatus;
import com.qdlc.p2p.common.constant.GeneralAccountType;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.LogTplNid;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.OrderNoUtil;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.dao.AccountDao;
import com.qdlc.p2p.dal.dao.AccountLogDao;
import com.qdlc.p2p.dal.dao.BorrowCollectionDao;
import com.qdlc.p2p.dal.dao.BorrowDao;
import com.qdlc.p2p.dal.dao.BorrowTenderDao;
import com.qdlc.p2p.dal.dao.ExperienceDao;
import com.qdlc.p2p.dal.dao.ExperienceTenderDao;
import com.qdlc.p2p.dal.dto.Account;
import com.qdlc.p2p.dal.dto.Borrow;
import com.qdlc.p2p.dal.dto.BorrowCollection;
import com.qdlc.p2p.dal.dto.BorrowTender;
import com.qdlc.p2p.dal.dto.Experience;
import com.qdlc.p2p.dal.dto.ExperienceTender;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.model.BorrowModel;
import com.qdlc.p2p.dal.model.interest.EachPlan;
import com.qdlc.p2p.dal.model.interest.InterestCalculator;

/**
 * 体验标
 *
 * @author wuaj
 */
@Service
public class SelfExperience extends AbstractStrategy {

    @Resource
    private BorrowDao borrowDao;

    @Resource
    private InterestService interestService;

    @Resource
    private BorrowTenderDao borrowTenderDao;

    @Resource
    private BorrowCollectionDao borrowCollectionDao;

	@Resource
    private AccountDao accountDao;

    @Resource
    private ExperienceDao experienceDao;

    @Resource
    private ExperienceTenderDao experienceTenderDao;

	@Resource
	private AccountLogService accountLogService;

	@Resource
	private AccountLogDao accountLogDao;

	public int getStrategyType() {
        return BorrowType.EXPERIENCE;// 体验标
    }

    @Override
    public void tender(BorrowModel borrowModel, User tenderUser) {
        logger.info(MessageFormat.format("用户:{0} 正在投体验标", tenderUser.getUserName()));

        String orderNo = OrderNoUtil.getInstance().getSerialNumber();  //订单号
        borrowModel.setTenderBilNo(orderNo);

        Date tenderTime = DateUtil.getNow();  // 投标时间
        borrowModel.setTenderBilDate(DateUtil.dateStr3(tenderTime));  // 投标时间

        double tenderAccount = borrowModel.getMoney();  // 投标金额
        Borrow borrow = borrowDao.find(borrowModel.getId()); // 标

        logger.info(MessageFormat.format("体验金投标标ID:{0} 体验券金额:{1} 体验券ID:{2}", borrowModel.getId(), tenderAccount, borrowModel.getExperiences()[0]));

        InterestCalculator ic = interestService.experienceInterestCalculator(borrowModel, tenderTime); // 计算利息
        BorrowTender borrowTender = saveBorrowTender(borrowModel, borrow, tenderUser, ic, BorrowTenderType.FROM_SITE); // 生成投标记录

        // 体验金投标记录
        Global.setTransfer(LogTplNid.LOG_TPL_KEY, LogTplNid.EXPERIENCE_TENDER);
        Global.setTransfer("web_url", WEB_URL);
        Global.setTransfer("borrow", borrow);
        Global.setTransfer("money", tenderAccount);
		accountLogService.addAccountLog(tenderUser.getUserId(), 0L, tenderAccount);

        // 更新已投金额 (已投金额 + 投标金额)
        double accountYes = BigDecimalUtil.add(borrowModel.getAccountYes(), tenderAccount); // 已投金额

        // 计算 投标比例
        double tenderTotalAccount = borrowModel.getAccount();  // 标总金额
        double scales = BigDecimalUtil.div(accountYes, tenderTotalAccount) * 100; // 投资比例
        // 重新计算 避免round而导致99.99变成100
        scales = scales >= 99.99 && scales < 100 ? 99.99 : BigDecimalUtil.round(scales); // 投资比例

        // 更新投标金额 投标次数作为更新条件 保存投标的原子性
        borrow = borrowDao.tenderUpdate(borrowModel.getId(), tenderAccount, scales, borrowModel.getStatus(), borrowModel.getTenderTimes());

        // 放款记录生成
        experienceCreateCollectionList(borrowTender, ic, borrow);

        // 用户资金信息
        Account account = accountDao.findByUserId(tenderUser.getUserId());

        // 待收利息生成记录
        Global.setTransfer(LogTplNid.LOG_TPL_KEY, LogTplNid.EXPERIENCE_WAIT_INTEREST);
        Global.setTransfer("web_url", WEB_URL);
        Global.setTransfer("borrow", borrow);
        Global.setTransfer("money", borrowTender.getInterest()); // 利息
        account.setCollection(BigDecimalUtil.add(account.getCollection(), borrowTender.getInterest()));
		accountLogDao.addAccountLog(account, GeneralAccountType.PLATFORM, tenderAccount);
        accountDao.update(account);// 待收保存

        // 使用体验金
        for (long experienceId : borrowModel.getExperiences()) {
            Experience experience = experienceDao.find(experienceId);
            // 防止体验券 在其它地方被使用或被管理员作废
            if (experience.getStatus() != ExperienceStatus.UNUSED) {
                logger.error(MessageFormat.format("该体验券已被使用或作废!状态:{0}", experience.getStatus()));
                throw new BusinessException("该体验券已被使用或作废!");
            }
            // 保存体验金投标信息
            ExperienceTender experienceTender = new ExperienceTender();
            experienceTender.setUser(tenderUser);
            experienceTender.setExperience(experience);
            experienceTender.setBorrow(borrow);
            experienceTender.setTender(borrowTender);
            experienceTender.setCapital(experience.getAmount()); // 本金
            experienceTender.setInterest(borrowTender.getInterest()); // 目前只能使用一张体验券,所以此利息就是体验券产生的
            experienceTender.setStatus(ExperienceTenderStatus.SUCCESS);
            experienceTender.setAddTime(DateUtil.getNow());
            experienceTenderDao.save(experienceTender);

            // 更改体验券状态
            experience.setStatus(ExperienceStatus.USED);
            experience.setUseTime(DateUtil.getNow());
            experienceDao.update(experience);
        }
        logger.info(MessageFormat.format("用户:{0} 正常投体验标结束", tenderUser.getUserName()));
    }

    /**
     * 保存投标记录
     *
     * @param model              标模型
     * @param borrow             标
     * @param interestCalculator 利息
     * @param tenderType         来源
     */
    private BorrowTender saveBorrowTender(BorrowModel model, Borrow borrow, User tenderUser, InterestCalculator interestCalculator, byte tenderType) {
        BorrowTender borrowTender = new BorrowTender();
        borrowTender.setBorrow(borrow);
        borrowTender.setMoney(model.getMoney()); // 投标金额
        borrowTender.setTenderBilNo(model.getTenderBilNo()); // 订单号
        borrowTender.setTenderBilDate(model.getTenderBilDate()); // 投标日期
        borrowTender.setAddTime(DateUtil.getNow());  // 投标时间
        borrowTender.setAddIp(model.getAddIp()); // IP地址
        borrowTender.setUser(tenderUser); // 投标用户
        borrowTender.setTenderType(tenderType); // 投标来源
        borrowTender.setAccount(model.getMoney());// 体验券金额

        //borrowTender.setStatus(BorrowTenderStatus.SUCCESS); // 投标成功
        borrowTender.setStatus(BorrowTenderStatus.PROCESSED); // 投标被处理
        borrowTender.setRealAmount(0.00);// 投标金额

        double interest = BigDecimalUtil.sub(interestCalculator.repayTotal(), borrowTender.getAccount()); // 利息
        borrowTender.setRepaymentAccount(interest); // 利息+本金(实际本金为0 归还金额 = 利息)
        borrowTender.setInterest(interest);      // 还款利息
        borrowTender.setWaitAccount(interest);// 代收金额(实际本金为0 代收金额 = 代收利息)
        borrowTender.setWaitInterest(interest); // 代收利息
        borrowTender.setRepaymentTime(DateUtil.rollDay(borrowTender.getAddTime(), model.getTimeLimit())); // 还款时间
        borrowTenderDao.save(borrowTender);
        return borrowTender;
    }

    /**
     * 生成体验券 待收记录
     */
    private List<BorrowCollection> experienceCreateCollectionList(BorrowTender borrowTender, InterestCalculator ic, Borrow borrow) {
        List<BorrowCollection> collectList = new ArrayList<BorrowCollection>();
        List<EachPlan> eachPlanList = ic.getEachPlanList();
        // 拼装Collection对象 批量插入还款表
        int i = 0;
        double totalInterest = 0; //利息总和
        double totalCapital = 0; //本金总和

        BorrowCollection borrowCollection;
        for (EachPlan eachPlan : eachPlanList) {
            borrowCollection = new BorrowCollection();
            borrowCollection.setBorrow(borrow); // 标
            borrowCollection.setTender(borrowTender); // 投标
            borrowCollection.setUser(borrowTender.getUser());// 投标用户

            borrowCollection.setInterest(eachPlan.getInterest()); // 利息
            borrowCollection.setCapital(eachPlan.getCapital());// 本金
            borrowCollection.setRepaymentAccount(eachPlan.getTotal()); // 预还金额
            borrowCollection.setStatus(BorrowCollectionStatus.NO_REPAYMENT); // 未还款
            borrowCollection.setRepaymentYesAccount(0.00);// 已还金额
            borrowCollection.setLateDays(0); // 逾期天数
            borrowCollection.setLateInterest(0.00); // 逾期利息

            double borrowFee = SystemConfigHelper.getDoubleValue(SystemConfigHelper.Nid.INVESTOR_MANAGE_FEE);
            borrowFee = BigDecimalUtil.mul(borrowCollection.getInterest(), BigDecimalUtil.div(borrowFee, 100));
            borrowFee = BigDecimalUtil.round(borrowFee); // 四舍五入

            borrowCollection.setManageFee(borrowFee); // 管理费
            borrowCollection.setAddIp(Global.getIP()); // IP地址
            borrowCollection.setAddTime(DateUtil.getNow()); // 时间

            if (i == eachPlanList.size() - 1) { // 最后一期做减法(利息做减法，本金做减法，生成最后一期的待收本金，待收利息，)
                double interest = borrowTender.getInterest();
                // 计算最后一期利息
                double different = BigDecimalUtil.sub(interest, totalInterest);
                borrowCollection.setInterest(different); // 利息

                //计算最后一期本金
                double differentCapital = BigDecimalUtil.sub(borrowTender.getAccount(), totalCapital);
                borrowCollection.setCapital(differentCapital); // 本金
                borrowCollection.setRepaymentAccount(BigDecimalUtil.add(different)); // 归还金额
            }
            totalInterest = BigDecimalUtil.add(totalInterest, eachPlan.getInterest());
            totalCapital = BigDecimalUtil.add(totalCapital, eachPlan.getCapital());
            borrowCollection.setPeriod(i++);

            borrowCollection.setRepaymentTime(DateUtil.rollDay(borrowTender.getAddTime(), borrow.getTimeLimit())); // 还款时间
            collectList.add(borrowCollection);
        }
        borrowCollectionDao.save(collectList); // 生成 所有每期的归还计划表
        return collectList;
    }

}
